# 通知消息系统服务
import logging
from typing import List, Dict, Any, Optional
from django.contrib.auth.models import User
from django.core.mail import send_mail, EmailMultiAlternatives
from django.template.loader import render_to_string
from django.conf import settings
from django.utils import timezone
from datetime import datetime, timedelta
import json

from .models_system import SystemNotification

logger = logging.getLogger(__name__)


class NotificationService:
    """通知服务"""
    
    def __init__(self):
        self.email_enabled = getattr(settings, 'EMAIL_NOTIFICATIONS_ENABLED', True)
        self.sms_enabled = getattr(settings, 'SMS_NOTIFICATIONS_ENABLED', False)
        self.push_enabled = getattr(settings, 'PUSH_NOTIFICATIONS_ENABLED', True)
    
    def send_notification(self, 
                         users: List[User], 
                         title: str, 
                         message: str, 
                         notification_type: str = 'info',
                         channels: List[str] = None,
                         template_name: str = None,
                         template_context: Dict = None,
                         priority: str = 'medium',
                         action_url: str = None,
                         expires_at: datetime = None):
        """发送通知"""
        
        if channels is None:
            channels = ['system']  # 默认只发送系统通知
        
        results = {
            'system': [],
            'email': [],
            'sms': [],
            'push': []
        }
        
        # 发送系统通知
        if 'system' in channels:
            system_results = self._send_system_notifications(
                users, title, message, notification_type, priority, action_url, expires_at
            )
            results['system'] = system_results
        
        # 发送邮件通知
        if 'email' in channels and self.email_enabled:
            email_results = self._send_email_notifications(
                users, title, message, template_name, template_context
            )
            results['email'] = email_results
        
        # 发送短信通知
        if 'sms' in channels and self.sms_enabled:
            sms_results = self._send_sms_notifications(users, title, message)
            results['sms'] = sms_results
        
        # 发送推送通知
        if 'push' in channels and self.push_enabled:
            push_results = self._send_push_notifications(users, title, message)
            results['push'] = push_results
        
        return results
    
    def _send_system_notifications(self, 
                                  users: List[User], 
                                  title: str, 
                                  message: str, 
                                  notification_type: str,
                                  priority: str,
                                  action_url: str,
                                  expires_at: datetime) -> List[Dict]:
        """发送系统通知"""
        results = []
        
        for user in users:
            try:
                notification = SystemNotification.objects.create(
                    user=user,
                    title=title,
                    message=message,
                    notification_type=notification_type,
                    priority=priority,
                    action_url=action_url,
                    expires_at=expires_at
                )
                
                results.append({
                    'user_id': user.id,
                    'success': True,
                    'notification_id': notification.id
                })
                
            except Exception as e:
                logger.error(f"发送系统通知失败 - 用户: {user.username}, 错误: {e}")
                results.append({
                    'user_id': user.id,
                    'success': False,
                    'error': str(e)
                })
        
        return results
    
    def _send_email_notifications(self, 
                                 users: List[User], 
                                 title: str, 
                                 message: str,
                                 template_name: str = None,
                                 template_context: Dict = None) -> List[Dict]:
        """发送邮件通知"""
        results = []
        
        if not template_name:
            template_name = 'assets/notifications/email_notification.html'
        
        if not template_context:
            template_context = {}
        
        for user in users:
            if not user.email:
                results.append({
                    'user_id': user.id,
                    'success': False,
                    'error': '用户邮箱为空'
                })
                continue
            
            try:
                # 准备模板上下文
                context = {
                    'user': user,
                    'title': title,
                    'message': message,
                    'site_name': getattr(settings, 'SITE_NAME', '固定资产管理系统'),
                    **template_context
                }
                
                # 渲染邮件内容
                html_content = render_to_string(template_name, context)
                text_content = render_to_string(
                    template_name.replace('.html', '.txt'), 
                    context
                )
                
                # 创建邮件
                email = EmailMultiAlternatives(
                    subject=title,
                    body=text_content,
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    to=[user.email]
                )
                email.attach_alternative(html_content, "text/html")
                
                # 发送邮件
                email.send()
                
                results.append({
                    'user_id': user.id,
                    'success': True,
                    'email': user.email
                })
                
            except Exception as e:
                logger.error(f"发送邮件通知失败 - 用户: {user.username}, 错误: {e}")
                results.append({
                    'user_id': user.id,
                    'success': False,
                    'error': str(e)
                })
        
        return results
    
    def _send_sms_notifications(self, users: List[User], title: str, message: str) -> List[Dict]:
        """发送短信通知"""
        results = []
        
        # 这里集成短信服务提供商的API
        # 例如：阿里云短信、腾讯云短信等
        
        for user in users:
            # 获取用户手机号
            phone = getattr(user, 'phone', None) or getattr(user.profile, 'phone', None) if hasattr(user, 'profile') else None
            
            if not phone:
                results.append({
                    'user_id': user.id,
                    'success': False,
                    'error': '用户手机号为空'
                })
                continue
            
            try:
                # 这里调用短信服务API
                # 示例代码（需要根据实际短信服务商调整）
                sms_result = self._send_sms_via_provider(phone, title, message)
                
                results.append({
                    'user_id': user.id,
                    'success': sms_result['success'],
                    'phone': phone,
                    'message_id': sms_result.get('message_id'),
                    'error': sms_result.get('error')
                })
                
            except Exception as e:
                logger.error(f"发送短信通知失败 - 用户: {user.username}, 错误: {e}")
                results.append({
                    'user_id': user.id,
                    'success': False,
                    'error': str(e)
                })
        
        return results
    
    def _send_sms_via_provider(self, phone: str, title: str, message: str) -> Dict:
        """通过短信服务商发送短信"""
        # 这里是示例代码，需要根据实际使用的短信服务商进行实现
        # 例如使用阿里云短信服务
        
        try:
            # 示例：使用阿里云短信
            # from aliyunsdkcore.client import AcsClient
            # from aliyunsdkdysmsapi.request.v20170525 import SendSmsRequest
            
            # client = AcsClient(settings.ALIYUN_ACCESS_KEY_ID, settings.ALIYUN_ACCESS_KEY_SECRET, 'cn-hangzhou')
            # request = SendSmsRequest.SendSmsRequest()
            # request.set_PhoneNumbers(phone)
            # request.set_SignName(settings.SMS_SIGN_NAME)
            # request.set_TemplateCode(settings.SMS_TEMPLATE_CODE)
            # request.set_TemplateParam(json.dumps({'title': title, 'message': message}))
            
            # response = client.do_action_with_exception(request)
            # result = json.loads(response)
            
            # if result.get('Code') == 'OK':
            #     return {
            #         'success': True,
            #         'message_id': result.get('BizId')
            #     }
            # else:
            #     return {
            #         'success': False,
            #         'error': result.get('Message')
            #     }
            
            # 暂时返回模拟结果
            logger.info(f"模拟发送短信到 {phone}: {title} - {message}")
            return {
                'success': True,
                'message_id': f'mock_{timezone.now().timestamp()}'
            }
            
        except Exception as e:
            return {
                'success': False,
                'error': str(e)
            }
    
    def _send_push_notifications(self, users: List[User], title: str, message: str) -> List[Dict]:
        """发送推送通知"""
        results = []
        
        # 这里集成推送服务
        # 例如：Firebase、极光推送等
        
        for user in users:
            try:
                # 获取用户的推送token
                push_token = self._get_user_push_token(user)
                
                if not push_token:
                    results.append({
                        'user_id': user.id,
                        'success': False,
                        'error': '用户推送token为空'
                    })
                    continue
                
                # 发送推送通知
                push_result = self._send_push_via_provider(push_token, title, message)
                
                results.append({
                    'user_id': user.id,
                    'success': push_result['success'],
                    'push_token': push_token,
                    'message_id': push_result.get('message_id'),
                    'error': push_result.get('error')
                })
                
            except Exception as e:
                logger.error(f"发送推送通知失败 - 用户: {user.username}, 错误: {e}")
                results.append({
                    'user_id': user.id,
                    'success': False,
                    'error': str(e)
                })
        
        return results
    
    def _get_user_push_token(self, user: User) -> Optional[str]:
        """获取用户推送token"""
        # 这里从用户配置或设备表中获取推送token
        # 示例代码
        try:
            if hasattr(user, 'profile') and hasattr(user.profile, 'push_token'):
                return user.profile.push_token
            
            # 或者从设备表中获取
            # from .models import UserDevice
            # device = UserDevice.objects.filter(user=user, is_active=True).first()
            # return device.push_token if device else None
            
            return None
        except Exception:
            return None
    
    def _send_push_via_provider(self, push_token: str, title: str, message: str) -> Dict:
        """通过推送服务商发送推送"""
        try:
            # 示例：使用Firebase推送
            # from pyfcm import FCMNotification
            
            # push_service = FCMNotification(api_key=settings.FCM_SERVER_KEY)
            # result = push_service.notify_single_device(
            #     registration_id=push_token,
            #     message_title=title,
            #     message_body=message
            # )
            
            # if result['success']:
            #     return {
            #         'success': True,
            #         'message_id': result['results'][0]['message_id']
            #     }
            # else:
            #     return {
            #         'success': False,
            #         'error': result['results'][0]['error']
            #     }
            
            # 暂时返回模拟结果
            logger.info(f"模拟发送推送到 {push_token}: {title} - {message}")
            return {
                'success': True,
                'message_id': f'push_mock_{timezone.now().timestamp()}'
            }
            
        except Exception as e:
            return {
                'success': False,
                'error': str(e)
            }
    
    def send_bulk_notification(self, 
                              notification_data: List[Dict],
                              batch_size: int = 100) -> Dict:
        """批量发送通知"""
        total_sent = 0
        total_failed = 0
        results = []
        
        # 分批处理
        for i in range(0, len(notification_data), batch_size):
            batch = notification_data[i:i + batch_size]
            
            for item in batch:
                try:
                    result = self.send_notification(**item)
                    results.append(result)
                    
                    # 统计成功和失败数量
                    for channel_results in result.values():
                        for channel_result in channel_results:
                            if channel_result.get('success'):
                                total_sent += 1
                            else:
                                total_failed += 1
                                
                except Exception as e:
                    logger.error(f"批量发送通知失败: {e}")
                    total_failed += 1
        
        return {
            'total_sent': total_sent,
            'total_failed': total_failed,
            'results': results
        }
    
    def create_notification_template(self, 
                                   name: str, 
                                   title_template: str, 
                                   message_template: str,
                                   notification_type: str = 'info',
                                   channels: List[str] = None) -> Dict:
        """创建通知模板"""
        from .models_notification import NotificationTemplate
        
        try:
            template = NotificationTemplate.objects.create(
                name=name,
                title_template=title_template,
                message_template=message_template,
                notification_type=notification_type,
                default_channels=channels or ['system']
            )
            
            return {
                'success': True,
                'template_id': template.id,
                'message': '通知模板创建成功'
            }
            
        except Exception as e:
            logger.error(f"创建通知模板失败: {e}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def send_template_notification(self, 
                                  template_name: str, 
                                  users: List[User],
                                  context: Dict = None,
                                  channels: List[str] = None) -> Dict:
        """使用模板发送通知"""
        from .models_notification import NotificationTemplate
        
        try:
            template = NotificationTemplate.objects.get(name=template_name, is_active=True)
            
            # 渲染模板
            rendered_title = template.render_title(context or {})
            rendered_message = template.render_message(context or {})
            
            # 使用模板的默认渠道或指定渠道
            notification_channels = channels or template.default_channels
            
            # 发送通知
            return self.send_notification(
                users=users,
                title=rendered_title,
                message=rendered_message,
                notification_type=template.notification_type,
                channels=notification_channels
            )
            
        except NotificationTemplate.DoesNotExist:
            return {
                'success': False,
                'error': f'通知模板 "{template_name}" 不存在'
            }
        except Exception as e:
            logger.error(f"使用模板发送通知失败: {e}")
            return {
                'success': False,
                'error': str(e)
            }


# 全局通知服务实例
notification_service = NotificationService()


# 便捷函数
def send_notification(users, title, message, **kwargs):
    """发送通知的便捷函数"""
    if isinstance(users, User):
        users = [users]
    
    return notification_service.send_notification(users, title, message, **kwargs)


def send_email_notification(users, title, message, template_name=None, template_context=None):
    """发送邮件通知的便捷函数"""
    if isinstance(users, User):
        users = [users]
    
    return notification_service.send_notification(
        users=users,
        title=title,
        message=message,
        channels=['email'],
        template_name=template_name,
        template_context=template_context
    )


def send_system_notification(users, title, message, notification_type='info', priority='medium'):
    """发送系统通知的便捷函数"""
    if isinstance(users, User):
        users = [users]
    
    return notification_service.send_notification(
        users=users,
        title=title,
        message=message,
        notification_type=notification_type,
        priority=priority,
        channels=['system']
    )